package com.xysoft.admin.service.impl;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.disk.DiskFileItem;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import com.xysoft.admin.common.ElementConst;
import com.xysoft.admin.common.PageModel;
import com.xysoft.admin.common.SessionInfo;
import com.xysoft.admin.dto.ActionDTO;
import com.xysoft.admin.dto.OrganizationDTO;
import com.xysoft.admin.dto.UserDTO;
import com.xysoft.admin.service.IUserService;
import com.xysoft.model.Action;
import com.xysoft.model.Organization;
import com.xysoft.model.Role;
import com.xysoft.model.RoleAction;
import com.xysoft.model.SystemType;
import com.xysoft.model.User;
import com.xysoft.model.UserAction;
import com.xysoft.util.DateUtil;
import com.xysoft.util.Encrypt;
import com.xysoft.util.JsonUtil;
import com.xysoft.util.RequestUtil;

@Component
@SuppressWarnings("unchecked")
public class UserServiceImpl extends BaseServiceImpl implements IUserService {

	@Transactional
	public String get(HttpServletRequest request, HttpSession session) {
		SessionInfo sessionInfo = RequestUtil.getSession(request, session);
		List<SystemType> types = this.getBaseDao().find("from SystemType s where s.deleted = 0 and belong = ?", 
				ElementConst.USERTYPE);
		Map<Integer, String> typeMaps = new HashMap<Integer, String>();
		for (SystemType type : types) {
			typeMaps.put(type.getId(), type.getName());
		}
		List<Organization> organs = this.getBaseDao().find("from Organization o where o.deleted = 0 and o.keyChar like ?", 
				sessionInfo.getKeyChar() + "%");
		Map<Integer, Organization> organMaps = new HashMap<Integer, Organization>();
		for (Organization organ : organs) {
			organMaps.put(organ.getId(), organ);
		}
		int page = Integer.valueOf(RequestUtil.getValue(request, "page"));
		int limit = Integer.valueOf(RequestUtil.getValue(request, "limit"));
		String hql = "from User u where u.deleted = 0 and u.front = 1 and u.organization.keyChar like ?";
		List<Object> values = new ArrayList<Object>();
		values.add(sessionInfo.getKeyChar() + "%");
		String username = RequestUtil.getValue(request, "username");
		if (username != null) {
			hql = hql + " and u.username like ?";
			values.add("%" + username + "%");
		}
		String truename = RequestUtil.getValue(request, "truename");
		if (truename != null) {
			hql = hql + " and u.truename like ?";
			values.add("%" + truename + "%");
		}
		String nickName = RequestUtil.getValue(request, "nickName");
		if (nickName != null) {
			hql = hql + " and u.nickName like ?";
			values.add("%" + nickName + "%");
		}
		List<User> users = this.getBaseDao().find(hql, page, limit, values);
		List<UserDTO> dtos = new ArrayList<UserDTO>();
		for(User user : users) {
			UserDTO dto = new UserDTO();
			BeanUtils.copyProperties(user, dto);
			dto.setSbirthday(DateUtil.format(user.getBirthday()));
			dto.setSlastTime(DateUtil.format(user.getLastTime()));
			dto.setSregisterDate(DateUtil.format(user.getRegisterDate()));
			int organId = user.getOrganization().getId();
			dto.setSorgan(organId);
			Organization tempOrgan = organMaps.get(organId);
			dto.setSorganName(tempOrgan.getName());
			int typeId = user.getSystemType().getId();
			dto.setSsystemType(typeId);
			dto.setSsystemTypeName(typeMaps.get(typeId));
			dtos.add(dto);
		}
		long count = this.getBaseDao().count("select count(*) " + hql, values);
		PageModel pm = new PageModel();
		pm.setTotal(count);
		pm.setDatas(dtos);
		return JsonUtil.toStringFromObject(pm);
	}
	
	@Transactional(readOnly = true)
	public String getOrgan(HttpServletRequest request, HttpSession session) {
		SessionInfo sessionInfo = RequestUtil.getSession(request, session);
		User user = (User)this.getBaseDao().get(User.class, sessionInfo.getUser().getId());
		Organization organ = user.getOrganization();
		String node = request.getParameter("node");
		//查询SQL语句
		String hql = "from Organization o where o.deleted = 0";
		//查询SQL值
		List<Object> values = new ArrayList<Object>();
		if (node == null || "root".equals(node)) {
			hql = hql + " and o.id = ?";
			values.add(organ.getId());
		} else {
			hql = hql + " and o.keyChar like ? and o.parent.id = ?";
			values.add(organ.getKeyChar() + "%");
			values.add(Integer.valueOf(node));
		}
		List<Organization> organizations = this.getBaseDao().find(hql, values);
		List<OrganizationDTO> dtos = new ArrayList<OrganizationDTO>();
		for (Organization oo : organizations) {
			OrganizationDTO dto = new OrganizationDTO();
			BeanUtils.copyProperties(oo, dto);
			if (oo.getNumber() > 0) {
				dto.setExpandable(true);
				dto.setLeaf(false);
			} else {
				dto.setExpandable(false);
				dto.setLeaf(true);
			}
			dtos.add(dto);
		}
		return JsonUtil.toString(dtos);
	}
	
	@Transactional
	public Map<String, Object> addOrModify(HttpServletRequest request, HttpSession session) {
		SessionInfo sessionInfo = RequestUtil.getSession(request, session);
		int organId = Integer.valueOf(RequestUtil.getValue(request, "sorgan"));
		Organization organ = (Organization)this.getBaseDao().get(Organization.class, organId);
		if (!organ.getKeyChar().startsWith(sessionInfo.getKeyChar()) 
				|| organ.isDeleted()) return null;
		Map<String,Object> modelMap = new HashMap<String,Object>(4);
		modelMap.put("success", true);
		modelMap.put("obj", false);
		modelMap.put("title", "保存失败！");
		String username = RequestUtil.getValue(request, "username").trim();
		if ("".equals(username) || username.length() < 6) {
			modelMap.put("msg", "登录名不能为空（大于或等于6个字符）.");
			return modelMap;
		} 
		long count = this.getBaseDao().count("select count(*) from User u where u.deleted = 0 and  u.username = ?", 
				username);
		String idStr = RequestUtil.getValue(request, "id"); 
		User user = null;
		String password = RequestUtil.getValue(request, "password").trim();
		String typeHql = "from SystemType s where s.deleted = 0 and s.belong = ? and s.value = ?";
		if ("".equals(idStr)) {
			if (count > 0) {
				modelMap.put("msg", "登录名已存在.");
				return modelMap;
			}
			if ("".equals(password)) {
				modelMap.put("msg", "登录密码不能为空（大于或等于6个字符）.");
				return modelMap;
			}
			user = new User();
			user.setDeleted(false);
			user.setFront(true);
			user.setLastTime(new Date());
			user.setRegisterDate(new Date());
			if (organ.getParent() == null) {
				SystemType type = (SystemType)this.getBaseDao().find(typeHql, 
						ElementConst.USERTYPE, ElementConst.USERTYPE_MEMBER).get(0);
				user.setSystemType(type);
			} else {
				SystemType type = (SystemType)this.getBaseDao().find(typeHql, 
						ElementConst.USERTYPE, ElementConst.USERTYPE_STUDENT).get(0);
				user.setSystemType(type);
			}
		} else {
			user = (User)this.getBaseDao().get(User.class, Integer.valueOf(idStr));
			if (!user.isFront() || user.isDeleted() || !user.getOrganization().getKeyChar()
					.startsWith(sessionInfo.getKeyChar())) return null;
			if (!username.equals(user.getUsername()) && count > 0) {
				modelMap.put("msg", "登录名已存在.");
				return modelMap;
			}
			if (organ.getParent() == null 
					&& !ElementConst.USERTYPE_MEMBER.equals(user.getSystemType().getValue())) {
				SystemType type = (SystemType)this.getBaseDao().find(typeHql, 
						ElementConst.USERTYPE, ElementConst.USERTYPE_MEMBER).get(0);
				user.setSystemType(type);
			} else if (ElementConst.USERTYPE_MEMBER.equals(user.getSystemType().getValue())) {
				SystemType type = (SystemType)this.getBaseDao().find(typeHql, 
						ElementConst.USERTYPE, ElementConst.USERTYPE_STUDENT).get(0);
				user.setSystemType(type);
			}
		}
		String repassword = RequestUtil.getValue(request, "repassword").trim();
		if (!"".equals(password) && (password.length() < 6 || !password.equals(repassword))) {
			modelMap.put("msg", "密码不合法.");
			return modelMap;
		}
		user.setUsername(username);
		if (!"".equals(password)) {
			user.setPassword(Encrypt.md5AndSha(password));
		}
		user.setEnabled(Boolean.valueOf(RequestUtil.getValue(request, "enabled")));
		user.setLimited(true);
		user.setMail(RequestUtil.getValue(request, "mail"));
		user.setMotto(RequestUtil.getValue(request, "motto"));
		user.setNickName(RequestUtil.getValue(request, "nickName"));
		user.setOrganization(organ);
		user.setPhone(RequestUtil.getValue(request, "phone"));
		user.setQq(RequestUtil.getValue(request, "qq"));
		user.setRemark(RequestUtil.getValue(request, "remark"));
		user.setSex(Integer.valueOf(RequestUtil.getValue(request, "sex")));
		user.setTruename(RequestUtil.getValue(request, "truename"));
		this.getBaseDao().save(user);
		modelMap.put("title", "保存成功！");
		modelMap.put("msg", "");
		modelMap.put("obj", true);
		return modelMap;
	}
	
	@Transactional
	public Map<String, Object> pic(HttpServletRequest request, HttpSession session) {
		SessionInfo sessionInfo = RequestUtil.getSession(request, session);
		int userId = Integer.valueOf(RequestUtil.getValue(request, "id"));
		User user = (User)this.getBaseDao().get(User.class, userId);
		if (!user.getOrganization().getKeyChar().startsWith(sessionInfo.getKeyChar()) 
				|| user.isDeleted() || !user.isFront()) return null;
		String targetFile = request.getSession().getServletContext().getRealPath(ElementConst.USERPICPATH) 
				+ File.separator;
		File target = new File(targetFile);
		if (!target.exists()) target.mkdirs();
		MultipartHttpServletRequest mulrequest = (MultipartHttpServletRequest)request;
		List<MultipartFile> files = mulrequest.getFiles("file");
		if (files.size() > 0) {
			CommonsMultipartFile file = (CommonsMultipartFile)files.get(0);
			DiskFileItem fileItem = (DiskFileItem) file.getFileItem();
			try {
				File fr = new File(targetFile + userId + this.getFileName(fileItem.getName()));
				FileCopyUtils.copy(file.getBytes(), fr);
				if (!user.isPic()) {
					user.setPic(true);
					this.getBaseDao().save(user);
				}
			} catch (Exception e) {
				e.printStackTrace();
				return null;
			}
		}
		Map<String,Object> modelMap = new HashMap<String,Object>(3);
		modelMap.put("success", true);
		modelMap.put("title", "上传成功！");
		modelMap.put("msg", "");
		return modelMap;
	}
	
	/**
	 * 获取文件扩展名 .
	 */
	private String getFileName(String str) {
		int index = str.lastIndexOf(".");
		if (-1 != index) {
			return str.substring(index);
		} else {
			return str;
		}
	}
	
	@Transactional
	public Map<String, Object> remove(HttpServletRequest request, HttpSession session) {
		SessionInfo sessionInfo = RequestUtil.getSession(request, session);
		User user = (User)this.getBaseDao().get(User.class, 
				Integer.valueOf(RequestUtil.getValue(request, "id")));
		if (!user.getOrganization().getKeyChar().startsWith(sessionInfo.getKeyChar()) 
				|| user.isDeleted() || !user.isFront()) return null;
		Organization organ = (Organization)this.getBaseDao().get(Organization.class, sessionInfo.getOrgId());
		if (organ.getParent() == null) {
			user.setDeleted(true);
		} else {
			Organization organTemp = (Organization)this.getBaseDao().find("from Organization o where o.deleted = 0 and o.parent = null").get(0);
			String typeHql = "from SystemType s where s.deleted = 0 and s.belong = ? and s.value = ?";
			SystemType type = (SystemType)this.getBaseDao().find(typeHql, 
					ElementConst.USERTYPE, ElementConst.USERTYPE_MEMBER).get(0);
			user.setOrganization(organTemp);
			user.setSystemType(type);
		}
		this.getBaseDao().save(user);
		Map<String,Object> modelMap = new HashMap<String,Object>(3);
		modelMap.put("success", true);
		modelMap.put("ok", true);
		modelMap.put("msg", "删除成功！");
		return modelMap;
	}
	
	@Transactional
	public String getAllAction() {
		List<Action> actions = this.getBaseDao().find("from Action a where a.front = 1 and a.leaf = 1");
		List<ActionDTO> dtos = new ArrayList<ActionDTO>();
		for (Action action : actions) {
			ActionDTO dto = new ActionDTO();
			dto.setId(action.getId());
			dto.setName(action.getKeyName());
			dtos.add(dto);
		}
		return JsonUtil.toString(dtos);
	}

	@Transactional
	public Map<String, Object> getAuto(HttpServletRequest request, HttpSession session) {
		SessionInfo sessionInfo = RequestUtil.getSession(request, session);
		User user = (User)this.getBaseDao().get(User.class, 
				Integer.valueOf(RequestUtil.getValue(request, "id")));
		if (!user.getOrganization().getKeyChar().startsWith(sessionInfo.getKeyChar()) 
				|| user.isDeleted() || !user.isFront()) return null;
		String roleHQL = "from Role r where r.front = 1 and r.organization.id = ?";
		String uaHQL = "from UserAction ua where ua.rule = ? and ua.user.id = ?";
		Organization organ = (Organization)this.getBaseDao().get(Organization.class, sessionInfo.getOrgId());
		Organization organTemp = getRootOrgan(organ);
		//获取角色权限
		List<Role> roles = this.getBaseDao().find(roleHQL, organTemp.getId());
		List<Integer> hasLst = new ArrayList<Integer>();
		if (roles.size() > 0) {
			Role role = roles.get(0);
			Set<RoleAction> ras = role.getRoleActions();
			for (RoleAction ra : ras) {
				hasLst.add(ra.getAction().getId());
			}
		}
		//获取用户权限
		List<Object> values = new ArrayList<Object>();
		if (organ.getParent() == null) {
			values.add(1);
		} else {
			values.add(2);
		}
		values.add(user.getId());
		List<UserAction> uas = this.getBaseDao().find(uaHQL, values);
		for (UserAction ua : uas) {
			Integer tge = ua.getAction().getId();
			if (ua.isEnable()) {
				if (hasLst.contains(tge)) continue;
				else hasLst.add(tge);
			} else {
				if (hasLst.contains(tge)) hasLst.remove(tge);
				else continue;
			}
		}
		Map<String,Object> modelMap = new HashMap<String,Object>(3);
		modelMap.put("success", true);
		modelMap.put("obj", hasLst);
		return modelMap;
	}
	
	private Organization getRootOrgan(Organization organ) {
		if (organ.getKeyChar().split(";").length <= 2) return organ;
		else return getRootOrgan(organ.getParent());
	}

	@Transactional
	public Map<String, Object> config(HttpServletRequest request, HttpSession session) {
		SessionInfo sessionInfo = RequestUtil.getSession(request, session);
		User user = (User)this.getBaseDao().get(User.class, 
				Integer.valueOf(RequestUtil.getValue(request, "id")));
		if (!user.getOrganization().getKeyChar().startsWith(sessionInfo.getKeyChar()) 
				|| user.isDeleted() || !user.isFront()) return null;
		List<Action> actions = this.getBaseDao().find("from Action a where a.front = 1 and a.leaf = 1");
		Map<Integer, Action> actMaps = new HashMap<Integer, Action>();
		for (Action act : actions) {
			actMaps.put(act.getId(), act);
		}
		String roleHQL = "from Role r where r.front = 1 and r.organization.id = ?";
		String uaHQL = "from UserAction ua where ua.rule = ? and ua.user.id = ?";
		Organization organ = (Organization)this.getBaseDao().get(Organization.class, sessionInfo.getOrgId());
		Organization organTemp = getRootOrgan(organ);
		//获取角色权限
		List<Role> roles = this.getBaseDao().find(roleHQL, organTemp.getId());
		List<Integer> raLst = new ArrayList<Integer>();
		if (roles.size() > 0) {
			Role role = roles.get(0);
			Set<RoleAction> ras = role.getRoleActions();
			for (RoleAction ra : ras) {
				raLst.add(ra.getAction().getId());
			}
		}
		//获取用户权限
		List<Object> values = new ArrayList<Object>();
		if (organ.getParent() == null) {
			values.add(1);
		} else {
			values.add(2);
		}
		values.add(user.getId());
		List<UserAction> uas = this.getBaseDao().find(uaHQL, values);
		Map<Integer, UserAction> uaMaps = new HashMap<Integer, UserAction>();
		for (UserAction ua : uas) {
			uaMaps.put(ua.getAction().getId(), ua);
		}
		//匹配权限
		String autostr = RequestUtil.getValue(request, "autostr");
		if (!"".equals(autostr)) {
			String[] autos = autostr.split(";");
			for (String auto : autos) {
				Integer auInt = Integer.valueOf(auto);
				if (raLst.contains(auInt)) {
					raLst.remove(auInt);
				} else if (uaMaps.containsKey(auInt)) {
					UserAction ua = uaMaps.get(auInt);
					if (ua.isEnable()) uaMaps.remove(auInt);
				} else {
					if (actMaps.containsKey(auInt)) {
						UserAction ua = new UserAction();
						ua.setAction(actMaps.get(auInt));
						ua.setEnable(true);
						ua.setRule(Integer.valueOf(values.get(0).toString()));
						ua.setUser(user);
						this.getBaseDao().save(ua);
					}
				}
			}
		}
		for (Integer ra : raLst) {
			if (actMaps.containsKey(ra)) {
				if (!uaMaps.containsKey(ra)) {
					UserAction ua = new UserAction();
					ua.setAction(actMaps.get(ra));
					ua.setEnable(false);
					ua.setRule(Integer.valueOf(values.get(0).toString()));
					ua.setUser(user);
					this.getBaseDao().save(ua);
				} else {
					UserAction uaTemp = uaMaps.get(ra);
					if (uaTemp.isEnable()) {
						uaTemp.setEnable(false);
						this.getBaseDao().save(uaTemp);
					}
					uaMaps.remove(ra);
				}
			}
		}
		user.setUserActions(null);
		for (UserAction ua : uaMaps.values()) {
			this.getBaseDao().delete(ua);
		}
		Map<String,Object> modelMap = new HashMap<String,Object>(2);
		modelMap.put("success", true);
		modelMap.put("msg", "保存成功！");
		return modelMap;
	}

}
